package com.blb.demo6;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * XML配置的IOC工厂
 */
public class MyXMLBeanFactory {
    //配置文件名称
    private String fileName;
    //保存javabean的集合
    private Map<String,Object> beanMap = new HashMap<>();

    public MyXMLBeanFactory(String fileName) {
        this.fileName = fileName;
        parseXML();
    }
    /**
     * 解析XML
     */
    public void parseXML(){
        SAXReader reader = new SAXReader();
        try {
            //读取xml文件，获得文档对象
            Document doc = reader.read(MyXMLBeanFactory.class.getClassLoader().getResourceAsStream(fileName));
            //通过文档对象，获得根节点
            Element root = doc.getRootElement();
            //通过根节点，查找所有的bean节点
            List<Element> beans = root.elements("bean");
            //这次循环将对象实例化添加到map中
            for(Element bean : beans){
                //通过class属性，获得类型信息，实例化对象
                Class tClass = Class.forName(bean.attribute("class").getValue());
                Object beanObj = tClass.newInstance();
                //添加JavaBean到Map中id为键，对象为值
                String id = bean.attribute("id").getValue();
                beanMap.put(id,beanObj);
            }
            //这次循环是将bean中的属性进行初始化
            for(Element bean : beans) {
                //读取bean节点中的property节点
                List<Element> properties = bean.elements("property");
                for(Element property : properties) {
                    Attribute value = property.attribute("value");
                    if(value != null) {
                        //如果是value，直接赋值
                        String name = property.attribute("name").getValue();
                        //通过id在map中获得bean对象
                        Object beanObj = beanMap.get(bean.attribute("id").getValue());
                        //通过名字找到属性，通过反射赋值
                        Field field = beanObj.getClass().getDeclaredField(name);
                        field.setAccessible(true);
                        field.set(beanObj,value.getValue());
                    }
                    //如果是ref，从Map中查找对象进行赋值
                    Attribute ref = property.attribute("ref");
                    if(ref != null){
                        //通过ref找到需要注入到属性的对象
                        Object refObj = beanMap.get(ref.getValue());
                        //如果是value，直接赋值
                        String name = property.attribute("name").getValue();
                        //通过id在map中获得当前bean对象
                        Object beanObj = beanMap.get(bean.attribute("id").getValue());
                        //通过名字找到属性，通过反射赋值,将对象注入到属性中
                        Field field = beanObj.getClass().getDeclaredField(name);
                        field.setAccessible(true);
                        field.set(beanObj,refObj);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获得JavaBean
     * @param beanName
     * @return
     */
    public Object getBean(String beanName){
        return beanMap.get(beanName);
    }
}
